package cn.lbd.kill.server.service;

import cn.lbd.kill.model.entity.ItemKillSuccess;
import cn.lbd.kill.model.mapper.ItemKillSuccessMapper;
import javafx.concurrent.ScheduledService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * RabbitMQ死信队列缺陷：有许多订单在某个TTL集中失效，但是恰好RabbitMQ服务挂掉了。。。
 * 补充解决方案：基于@Scheduled注解的定时任务实现-批量获取status=0的订单并判断时间超过了TTL
 * 完整解决方案：结合线程池一起使用，规避单一线程处理多个任务调度的缺陷，支持多线程处理
 * 整体的逻辑就是，死信队列设置了180s失效，主要靠死信队列来做失效处理。假如MQ宕机，还有一个应急的定时器方案来弥补这个问题，定时器每10秒轮询一次，如果有30分钟没操作的订单就置为失效
 */
@Service
public class SchedulerService {
    private Logger logger = LoggerFactory.getLogger(SchedulerService.class);
    @Autowired(required = false)
    private ItemKillSuccessMapper itemKillSuccessMapper;
    @Autowired
    private Environment environment;

    //定时器从0秒开始，每隔十秒执行一次
    @Scheduled(cron = "0/30 * * * * ? ")
    public void expireOrder() {
        try {
            logger.info("T1...");
            List<ItemKillSuccess> itemKillSuccesses = itemKillSuccessMapper.schedulerExpireOrder();
            itemKillSuccesses.stream().forEach(i -> {
                //如果订单30分钟未付款就置为失效
                if (i != null && i.getDiffTime() > environment.getProperty("scheduler.expire.orders.time",Integer.class)) {
                    itemKillSuccessMapper.expireOrder(i.getCode());
                }
            });
        }catch (Exception e) {
            logger.error("定时获取status=0的订单并判断是否超过TTL，然后进行失效-发生异常：", e.fillInStackTrace());
        }
    }

    /*@Scheduled(cron = "0/11 * * * * ? ")
    public void expireOrder2() {
        logger.info("T2...");
    }

    @Scheduled(cron = "0/9 * * * * ? ")
    public void expireOrder3() {
        logger.info("T3...");
    }*/
}
